﻿#pragma once

#include "ITimer.h"
namespace LH
{
class BaseTimer : public ITimer
{
public:
    /* override from ITimer */
    TimerID schedule(
        TimerListener listener,
        std::chrono::milliseconds msecs) final override;

    /* override from ITimer */
    TimerID scheduleAtFixedRate(
        TimerListener listener,
        std::chrono::milliseconds msecs,
        std::chrono::milliseconds delay = std::chrono::milliseconds{ 0 }) final override;

    /* override from ITimer */
    TimerID scheduleAtFixedDelay(
        TimerListener listener,
        std::chrono::milliseconds msecs,
        std::chrono::milliseconds delay = std::chrono::milliseconds{ 0 }) final override;
     
protected:
    // 定时策略
    enum class Datum : uint8_t {
        NOT_SET = 0,        // 不重复执行
        FROM_NOW = 1,       // 执行时间计算从第一次执行时间开始计算
        FROM_LAST_TIMER = 2,// 执行时间从上一次执行时间开始计算
    };

    // 定时任务节点
    class TimerNode {
    public:
        TimerNode() = default;
        TimerNode(const TimerNode&rhs) = default;
        TimerNode(TimerListener cb,
            std::chrono::steady_clock::time_point _tp,
            std::chrono::milliseconds _interval,
            Datum _datum,
            TimerID _id = 0
        ) :callback(cb), tp(_tp),
            interval(_interval),
            datum(_datum), id(_id) {}

        TimerListener callback; // 回调函数
        std::chrono::steady_clock::time_point tp;// 执行时间点
        std::chrono::milliseconds  interval{ 0 }; // 时间间隔
        Datum datum{ Datum::NOT_SET }; // 执行策略
        TimerID id{0};  // 定时任务唯一id 
    };
     
    // 创建定时任务节点
    virtual TimerID doSchedule(TimerListener listener,
        std::chrono::milliseconds msecs,
        std::chrono::milliseconds delay,
        bool repeat,
        Datum repeatMode = Datum::NOT_SET) = 0; 

    // 触发定时任务
    // 返回 true,有执行定时任务；false,没有定时任务
    virtual  bool fireTimer(const std::chrono::steady_clock::time_point& tpNow) = 0;

    // 计算超时
    // 返回 -1，没有定时任务 
    virtual int32_t calculateTimeout(const std::chrono::steady_clock::time_point& now) = 0;

    // 无延时定义
    static constexpr std::chrono::milliseconds NO_DELAY{ 0 };
    // 无限值定义
    static constexpr int32_t TIMER_INFINITY{ -1 };
    
protected:
    static TimerID calculateTimerID() {
        // 这里计算TimerID，使用全局变量自增方式。
        // TimerID 最大值是0xFFFFFFFFFFFFFFFF。
        // 不可能同时存在这么多的定时任务
        // 自增方式计算TimerID 即可
        static TimerID currentId{ 0 };
        if (currentId == 0xFFFFFFFFFFFFFFFF) currentId += 2;
        else ++currentId;
        return currentId;
    }
};
} // namespace LH
